﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NGenORM.Library.Enum;

namespace NGenORM.Library.Code
{
	public class File
	{

		public List<Obj> Objects {get; set;}

		private string ProperCase(string str) {
			// if not value is provided throw an exception
			if (string.IsNullOrEmpty(str))
			throw new ArgumentException("A null value cannot be converted", str);
 
			if (str.Length < 2) {
				return str.ToUpper();
			}
 
			string converted = str.Substring(0, 1).Trim().ToUpper();
 
			for (int i = 1; i < str.Length; i++) {
				converted = (Char.IsUpper(str[i])) ? converted += " " : converted += str[i];
			}
 
			return converted;
		}

		private String GetDBType(int DataType) { 
			
			string Type = "";

			switch (DataType)
			{
				case 34: Type = "SqlDbType.Image"; break;
				case 35: Type = "SqlDbType.Text"; break;
				case 48: Type = "SqlDbType.TinyInt"; break;
				case 52: Type = "SqlDbType.SmallInt"; break;
				case 56: Type = "SqlDbType.Int"; break;
				case 58: Type = "SqlDbType.SmallDateTime"; break;
				case 59: Type = "SqlDbType.Real"; break;
				case 60: Type = "SqlDbType.Money"; break;
				case 61: Type = "SqlDbType.DateTime"; break;
				case 62: Type = "SqlDbType.Float"; break;
				case 99: Type = "SqlDbType.NText"; break;
				case 104: Type = "SqlDbType.Bit"; break;
				case 106: Type = "SqlDbType.Decimal"; break;
				case 108: Type = "SqlDbType.Decimal"; break;
				case 122: Type = "SqlDbType.SmallMoney"; break;
				case 127: Type = "SqlDbType.BigInt"; break;
				case 165: Type = "SqlDbType.VarBinary"; break;
				case 167: Type = "SqlDbType.VarChar"; break;
				case 173: Type = "SqlDbType.Binary"; break;
				case 175: Type = "SqlDbType.Char"; break;
				case 231: Type = "SqlDbType.NVarChar"; break;
				case 239: Type = "SqlDbType.NChar"; break;
				default: Type = ""; break;
			}

			return Type;

		}

		private String GetCodeType(int DataType) { 
			
			string Type = "";

			switch (DataType)
			{
				case 34: Type = "Image"; break; //Image
				case 35: Type = "String"; break; //Text
				case 48: Type = "Integer"; break; //TinyInt
				case 52: Type = "Integer"; break; //SmallInt
				case 56: Type = "Integer"; break; //Int
				case 58: Type = "DateTime"; break; //SmallDateTime
				case 59: Type = "Double"; break; //Real
				case 60: Type = "Decimal"; break; //Money
				case 61: Type = "DateTime"; break; //DateTime
				case 62: Type = "Double"; break; //Float
				case 99: Type = "String"; break; //NText
				case 104: Type = "Boolean"; break; //Bit
				case 106: Type = "Decimal"; break; //Decimal
				case 108: Type = "Double"; break;//Numeric
				case 122: Type = "Double"; break;//SmallMoney
				case 127: Type = "Integer"; break; //BigInt
				case 165: Type = "VarBinary"; break;
				case 167: Type = "String"; break; //VarChar
				case 173: Type = "Binary"; break;
				case 175: Type = "String"; break; //Char
				case 231: Type = "String"; break; //NVarChar
				case 239: Type = "String"; break; //NChar
				default: Type = ""; break;
			}

			return Type;

		}

		private StringBuilder CreateBeginClass(Obj obj) { 
		
			if (obj.Project.ClassAlias == null) {
				obj.Project.ClassAlias = "";
			}
			
			string aux = obj.Project.ClassAlias + ProperCase(obj.ObjectName.ToString());
			StringBuilder sb = new System.Text.StringBuilder();

			switch (obj.Project.LanguageType) {

				case LanguageType.CSharp:

					switch (obj.Project.ObjectType)
					{
						case ObjectType.Entity:

							sb.Append("public Class " + aux + "").AppendLine();
							sb.Append("{").AppendLine();
							sb.Append("").AppendLine();
							break;

						case ObjectType.Persistence:

							sb.Append("Public Class " + aux + "DAO : " + aux + "").AppendLine();
							sb.Append("{").AppendLine();
							sb.Append("").AppendLine();
							break;

						case ObjectType.Service:
							sb.Append("Public Class " + aux + "Servico").AppendLine();
							sb.Append("{").AppendLine();
							sb.Append("").AppendLine();
							break;
					}
					break;

				case LanguageType.VB:

					switch (obj.Project.ObjectType)
					{
						case ObjectType.Entity:

							sb.Append("Public Class " + aux + "").AppendLine();
							sb.Append("").AppendLine();
							break;

						case ObjectType.Persistence:

							sb.Append("Public Class " + aux + "DAO").AppendLine();
							sb.Append("    Inherits " + aux + "").AppendLine();
							sb.Append("").AppendLine();
							break;

						case ObjectType.Service:
							sb.Append("Public Class " + aux + "Servico").AppendLine();
							sb.Append("").AppendLine();
							break;
					}
					break;
			}

			return sb;

		}

		private StringBuilder CreateEndClass(Obj obj)
		{

			System.Text.StringBuilder sb = new System.Text.StringBuilder();

			switch (obj.Project.LanguageType)
			{
					 
				case LanguageType.CSharp:
					sb.Append("}").AppendLine();
					break;

				case LanguageType.VB:
					sb.Append("End Class").AppendLine();
					break;
			}

			return sb;

		}

		private StringBuilder CreateComment(Obj obj) { 

			System.Text.StringBuilder sb = new System.Text.StringBuilder();

			if (obj.Project.MethodComment == true)
			{

				if (obj.Project.ObjectType == ObjectType.Persistence || obj.Project.ObjectType == ObjectType.Service)
				{

					switch (obj.Project.LanguageType)
					{

						case LanguageType.CSharp:
							sb.Append("").AppendLine();
							break;

						case LanguageType.VB:
							foreach (MethodType item in obj.Project.MethodTypes)
							{

								switch (item)
								{
									case MethodType.Save:
										sb.Append("    ''' Método para Salvar(Inserir/Atualizar) objetos na Tabela " + obj.ObjectName.ToString() + "").AppendLine();
										break;
									case MethodType.Update:
										sb.Append("    ''' Método para Atualizar objetos na Tabela " + obj.ObjectName.ToString() + "").AppendLine();
										break;
									case MethodType.Insert:
										sb.Append("    ''' Método para Inserir objetos na Tabela " + obj.ObjectName.ToString() + "").AppendLine();
										break;
									case MethodType.Delete:
										sb.Append("    ''' Método para Excluir objetos na Tabela " + obj.ObjectName.ToString() + "").AppendLine();
										break;
									case MethodType.ListOne:
										sb.Append("    ''' Método para Retornar um objeto da Tabela " + obj.ObjectName.ToString() + "").AppendLine();
										break;
									case MethodType.ListAll:
										sb.Append("    ''' Método para Retornar uma lista de objetos da Tabela " + obj.ObjectName.ToString() + "").AppendLine();
										break;
									case MethodType.Execute:
										sb.Append("    ''' Método para Executar o objeto " + obj.ObjectName.ToString() + "").AppendLine();
										break;
								}

							}
							sb.Append("    ''' </summary>").AppendLine();
							sb.Append("    ''' <returns>Retorna True se o método for executado com Sucesso e Falso para Erro.</returns>").AppendLine();
							sb.Append("    ''' <remarks></remarks>").AppendLine();
							break;
					}

				}

				else {
					sb.Append("");
				}

			}

			else {
				sb.Append("");
			}

			return sb;

		}

		private StringBuilder CreateHeaderClass(Obj obj) {

			StringBuilder sb = new StringBuilder();

			if (obj.Project.ClassHeader == true){
				switch (obj.Project.LanguageType)
				{
					case LanguageType.CSharp:
						sb.Append("//-----------------------------------------------------").AppendLine();
						sb.Append("//Classe criada automaticamente pelo NGenORM").AppendLine();
						sb.Append("//Para maiores informações: www.4nsoftsolutions.com.br").AppendLine();
						sb.Append("//Data de Criação: " + DateTime.Now.ToString() + "").AppendLine();
						sb.Append("//Classe criada para manipular o objeto: " + obj.ObjectName.ToString() + "").AppendLine();
						sb.Append("//-----------------------------------------------------").AppendLine();
						sb.Append("").AppendLine();
						break;

					case LanguageType.VB:
						sb.Append("'-----------------------------------------------------").AppendLine();
						sb.Append("'Classe criada automaticamente pelo NGenORM").AppendLine();
						sb.Append("'Para maiores informações: www.4nsoftsolutions.com.br").AppendLine();
						sb.Append("'Data de Criação: " + DateTime.Now.ToString() + "").AppendLine();
						sb.Append("'Classe criada para manipular o objeto: " + obj.ObjectName.ToString() + "").AppendLine();
						sb.Append("'-----------------------------------------------------").AppendLine();
						sb.Append("").AppendLine();
						break;
				}
			}
			else {
				sb.Append("");
			}

			return sb;

		}

		private StringBuilder CreateNamespace(Obj obj) {

			StringBuilder sb = new StringBuilder();

			switch (obj.Project.LanguageType)
			{
				case LanguageType.CSharp:

					sb.Append("#region Namespace").AppendLine();
					sb.Append("").AppendLine();

					switch (obj.Project.ObjectType)
					{
						case ObjectType.Entity:
							sb.Append("").AppendLine();
							break;
						case ObjectType.Persistence:
							sb.Append("using " + obj.Project.ProjectName.ToString() + ".Entity;").AppendLine();
							sb.Append("using " + obj.Project.ProjectName.ToString() + ".Util;").AppendLine();
							break;
						case ObjectType.Service:
							sb.Append("using " + obj.Project.ProjectName.ToString() + ".Persistence;").AppendLine();
							sb.Append("using " + obj.Project.ProjectName.ToString() + ".Entity;").AppendLine();
							break;
					}
					break;

					sb.Append("").AppendLine();
					sb.Append("#endregion").AppendLine();
					sb.Append("").AppendLine();
					
				case LanguageType.VB:

					sb.Append("#Region " + "\"Namespace\"").AppendLine();
					sb.Append("").AppendLine();

					switch (obj.Project.ObjectType)
					{
						case ObjectType.Entity:
							sb.Append("").AppendLine();
							break;
						case ObjectType.Persistence:
							sb.Append("Imports " + obj.Project.ProjectName.ToString() + ".Entity").AppendLine();
							sb.Append("Imports " + obj.Project.ProjectName.ToString() + ".Util").AppendLine();
							break;
						case ObjectType.Service:
							sb.Append("Imports " + obj.Project.ProjectName.ToString() + ".Persistence").AppendLine();
							sb.Append("Imports " + obj.Project.ProjectName.ToString() + ".Entity").AppendLine();
							break;
					}
					break;

					sb.Append("").AppendLine();
					sb.Append("#End Region").AppendLine();
					sb.Append("").AppendLine();
			}

			return sb;

		}

		private StringBuilder CreateConstructorService(Obj obj) {

			StringBuilder sb = new StringBuilder();

			switch (obj.Project.LanguageType)
			{
				case LanguageType.CSharp:

					sb.Append("#region Construtor").AppendLine();
					sb.Append("").AppendLine();
					sb.Append("    /// <summary>").AppendLine();
					sb.Append("    /// Singleton Pattern").AppendLine();
					sb.Append("    /// </summary>").AppendLine();
					sb.Append("    /// <remarks></remarks>").AppendLine();
					sb.Append("    private void CreateDAO() {").AppendLine();
					sb.Append("        If (Dao == null) {").AppendLine();
					sb.Append("            Dao = New " + ProperCase(obj.ObjectName.ToString()) + "DAO();").AppendLine();
					sb.Append("        }").AppendLine();
					sb.Append("    }").AppendLine();
					sb.Append("").AppendLine();
					sb.Append("    public " + obj.ObjectName.ToString() + "Service() {").AppendLine();
					sb.Append("        CreateDAO();").AppendLine();
					sb.Append("    }").AppendLine();
					sb.Append("").AppendLine();

					sb.Append("").AppendLine();
					sb.Append("#endregion").AppendLine();
					sb.Append("").AppendLine();
					break;

				case LanguageType.VB:

					sb.Append("#Region \"Construtor\"").AppendLine();
					sb.Append("").AppendLine();
					sb.Append("    ''' <summary>").AppendLine();
					sb.Append("    ''' Singleton Pattern").AppendLine();
					sb.Append("    ''' </summary>").AppendLine();
					sb.Append("    ''' <remarks></remarks>").AppendLine();
					sb.Append("    Private Sub CreateDAO()").AppendLine();
					sb.Append("        If Dao is Nothing Then").AppendLine();
					sb.Append("            Dao = New " + ProperCase(obj.ObjectName.ToString()) + "DAO()").AppendLine();
					sb.Append("        End If").AppendLine();
					sb.Append("    End Sub").AppendLine();
					sb.Append("").AppendLine();
					sb.Append("    Public Sub New()").AppendLine();
					sb.Append("        CreateDAO()").AppendLine();
					sb.Append("    End Sub").AppendLine();
					sb.Append("").AppendLine();

					sb.Append("").AppendLine();
					sb.Append("#End Region").AppendLine();
					sb.Append("").AppendLine();
					break;
			}

		return sb;

		}

		private StringBuilder CreateAttributes(Obj obj) { 
			
			StringBuilder sb = new StringBuilder();
		
			string NameField = "";
			string Column = "";
			int TypeColumn = 0;
			bool IsNullable = false;
			string IsNullableAux = "";
			bool IsPrimaryKey = false;
			string TypeObject = "";
			string SharedPropertiesStr = "Shared ";

			switch (obj.Project.LanguageType)
			{
				case LanguageType.CSharp:

					sb.Append("#region Fields").AppendLine();
					sb.Append("").AppendLine();
					
					
					
					sb.Append("").AppendLine();
					sb.Append("#endregion").AppendLine();
					sb.Append("").AppendLine();
					break;
				case LanguageType.VB:
					sb.Append("#Region \"Fields\"").AppendLine();
					sb.Append("").AppendLine();
					
					
					
					sb.Append("").AppendLine();
					sb.Append("#End Region").AppendLine();
					sb.Append("").AppendLine();
					break;
			}
			
		//For Each dtRow As DataRow In Columns.Rows

		//    NameField = "f_" + dtRow.Item(1).ToString()
		//    Column = dtRow.Item(1).ToString()
		//    TypeColumn = CInt(dtRow.Item(2).ToString())
		//    IsNullable = CBool(dtRow.Item(3))
		//    IsPrimaryKey = CBool(dtRow.Item(4))
		//    TypeObject = CStr(dtRow.Item(5).ToString())

		//    If TypeObject.Trim = "P" Then
		//        NameField = NameField.Replace("@", "")
		//        Column = Column.Replace("@", "")
		//    End If

		//    NameField = NameField.Replace(" ", "_")
		//    Column = Column.Replace(" ", "_")

		//    varclsDataTypeDotNet.DataType = TypeColumn

		//    If AllowNulls Then
		//        If IsNullable And varclsDataTypeDotNet.Transform() <> "String" Then
		//            IsNullableAux = "?"
		//        Else
		//            IsNullableAux = ""
		//        End If
		//    Else
		//        IsNullableAux = ""
		//    End If

		//    If Not SharedProperties Then
		//        SharedPropertiesStr = ""
		//    End If

		//    sb.Append("    Private " + SharedPropertiesStr + NameField + " As " + varclsDataTypeDotNet.Transform() + IsNullableAux + "").AppendLine()

		//Next

		

		//Return sb

			return sb;

		}

	}

}
